package com.zyx.security.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zyx.security.mapper.RoleMapper;
import com.zyx.security.model.po.Role;
import com.zyx.security.model.po.User;
import com.zyx.security.mapper.UserMapper;
import com.zyx.security.mapper.UserRoleMapper;
import com.zyx.security.model.po.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>自定义 UserDetailService 实现</p>
 *
 * @author Yaxi.Zhang
 * @since 2022/9/18 08:54
 */
@Service
public class DaoUserDetailServiceImpl implements UserDetailsService {

    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;
    private final UserMapper userMapper;

    @Autowired
    public DaoUserDetailServiceImpl(UserMapper userMapper, UserRoleMapper userRoleMapper, RoleMapper roleMapper) {
        this.userMapper = userMapper;
        this.userRoleMapper = userRoleMapper;
        this.roleMapper = roleMapper;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.selectOne(new LambdaUpdateWrapper<User>().eq(User::getUsername, username));
        if (ObjectUtils.isEmpty(user)) {
            throw new RuntimeException("用户名不存在!");
        }
        // 找到用户对应的角色
        List<UserRole> userRoles = userRoleMapper.selectList(new LambdaUpdateWrapper<UserRole>().eq(UserRole::getUid, user.getId()));
        List<Role> roles = roleMapper.selectList(new LambdaUpdateWrapper<Role>().in(Role::getId,
                userRoles.stream().map(UserRole::getRid).collect(Collectors.toSet())));
        user.setRoles(roles);
        return user;
    }

}
